﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using PluginManager.Plugin;
using UnityEngine;
using Modding;
using System.Collections;

namespace RayGun
{

    public class RayScript : BlockScript
    {

        //LineRenderer lineRenderer;

        Vector3 orginPoint/*,direction*/;

        RaycastHit hitInfo;

        bool shootEnable = true;

        float strength = /*17.5f*/5f;
        float interval = /*0.02f*/0.1f;
        float recoil = /*1f*/0.2f;

        MKey fireKey;
        MSlider strengthSlider;
        MSlider intervalSlider;
        MSlider recoilSlider;
        MSlider bulletMassSlider;
        MSlider bulletDragSlider;
        MColourSlider bulletColourSlider;

        public override void SafeAwake()
        {
            fireKey = AddKey("Fire", "Fire", KeyCode.F);

            strengthSlider = AddSlider("Strength", "Strength", strength, 0f, 30f);
            strengthSlider.ValueChanged += (value) => { strength = value; };
            intervalSlider = AddSlider("Interval", "Interval", interval, 0.01f, 0.5f);
            intervalSlider.ValueChanged += (value) => { interval = value; };
            recoilSlider = AddSlider("Recoil", "Recoil", recoil, 0f, 1f);
            recoilSlider.ValueChanged += (value) => { recoil = value; };

            bulletMassSlider = AddSlider("Bullet Mass", "Bullet Mass", 0.1f, 0.1f, 1f);
            bulletDragSlider = AddSlider("Bullet Drag", "Bullet Drag", 0.1f, 0.1f, 1f);
            bulletColourSlider = AddColourSlider("Color", "Color", Color.yellow, false);

            //lineRenderer =  GetComponent<LineRenderer>()?? gameObject.AddComponent<LineRenderer>();
            
            //lineRenderer.material.shader = Shader.Find("Particles/Additive");
            //lineRenderer.material.color = Color.yellow;
            //lineRenderer.SetWidth(0.2f, 0.2f);
            //lineRenderer.enabled = false;

        }

        public override void SimulateUpdateAlways()
        {
            //if (fireKey.IsHeld )
            //{
            //    if (shootEnable)
            //    {
            //        direction = -transform.right;

            //        orginPoint = transform.position + direction * 2f + transform.forward * 0.5f;



            //        if (Physics.Raycast(orginPoint, direction, out hitInfo, 1000f))
            //        {
            //            lineRenderer.SetPosition(0, orginPoint);
            //            lineRenderer.SetPosition(1, hitInfo.point);
            //            StartCoroutine(shoot(hitInfo));
            //        }
            //        else
            //        {
            //            lineRenderer.SetPosition(0, orginPoint);
            //            lineRenderer.SetPosition(1, orginPoint + direction * 1000f);
            //            //lineRenderer.enabled = false;
            //            StartCoroutine(shoot());
            //        }


            //        lineRenderer.enabled = true;
            //    }


            //}
            //else
            //{
            //    lineRenderer.enabled = false;
            //    shootEnable = true;
            //}

            if (fireKey.IsHeld)
            {
                if (shootEnable)
                {
                    StartCoroutine(shootTest());
                }


            }
            else
            {
                
                shootEnable = true;
            }

        }

        private IEnumerator shoot(RaycastHit hit)
        {
            Rigidbody.AddForce(transform.right * 100f * recoil * strength);
            if (hit.rigidbody != null)
            {
                hit.rigidbody.AddForceAtPosition((hit.point - orginPoint) * strength, hit.point, ForceMode.Impulse);
            }
            shootEnable = false;

            yield return new WaitForSeconds(0.01f);
            //lineRenderer.enabled = false;
            yield return new WaitForSeconds(Mathf.Clamp(interval - 0.01f, 0f, Mathf.Infinity));

            shootEnable = true;
            
        }

        private IEnumerator shoot()
        {
            Rigidbody.AddForce(transform.right * 1000f * recoil);
            shootEnable = false;

            yield return new WaitForSeconds(0.01f);
            //lineRenderer.enabled = false;
            yield return new WaitForSeconds(Mathf.Clamp(interval - 0.01f, 0f, Mathf.Infinity));

            shootEnable = true;

        }

        private IEnumerator shootTest()
        {
            int index = 0;
            //Vector3 direction = -transform.right;
            //Vector3 spoint = transform.position + direction * 2f + transform.forward * 0.5f;
           
            Vector3 epoint = Vector3.zero;
            Rigidbody.AddForce(transform.right * 100f * recoil * strength);
            //lineRenderer.enabled = true;
            shootEnable = false;

            //while (index < 100)
            //{
            //    epoint = spoint + direction;
            //    lineRenderer.SetPosition(0, spoint);
            //    lineRenderer.SetPosition(1, epoint);

            //    if (Physics.Raycast(spoint, direction, out hitInfo, 1f))
            //    {
            //        Rigidbody.AddForce(transform.right * 100f * recoil * strength);
            //        if (hitInfo.rigidbody != null)
            //        {
            //            hitInfo.rigidbody.AddForceAtPosition((hitInfo.point - orginPoint) * strength, hitInfo.point, ForceMode.Impulse);
            //        }

            //        new GameObject("bullet");

            //        break;
            //    }




            //    index++;
            //    yield return 0;
            //    spoint = epoint;

            //}
            fire(transform.position - transform.right * 2f + transform.forward * 0.5f, -transform.right,Rigidbody.velocity);

            //lineRenderer.enabled = false;
            yield return new WaitForSeconds(interval);        
            shootEnable = true;

            void fire(Vector3 firePos, Vector3 direction, Vector3 velocity)
            {
                var go = new GameObject("Bullet");
                var bs = go.AddComponent<BulletScript>();
                bs.orginPosition = firePos;
                bs.direction = direction;
                bs.Strength = strength;
                bs.Velocity = velocity;
                bs.Mass = bulletMassSlider.Value;
                bs.Drag = bulletDragSlider.Value;
                bs.color = bulletColourSlider.Value;

            }

        }

    }

    public class BulletScript : MonoBehaviour
    {
        public float Strength { get; set; }
        public Vector3 Velocity { get; set; }
        public float Drag { get; set; } = 0.1f;
        public float Mass { get; set; } = 0.1f;
        public Vector3 GravityAcceleration { get; } = new Vector3(0, -23f, 0);

        public bool isCollision { get; private set; } = false;

        public Vector3 orginPosition;
        public Vector3 direction;
        public Color color = Color.yellow;

        private Vector3 sPoint;
        private Vector3 ePoint;
        private RaycastHit hitInfo;
        private LineRenderer lineRenderer;
        private float _time;

        private void Start()
        {
            Velocity = transform.InverseTransformDirection(direction) * Strength * Mass * 600f + Velocity;

            sPoint = ePoint = orginPosition;

            lineRenderer = gameObject.AddComponent<LineRenderer>();
            lineRenderer.material.shader = Shader.Find("Particles/Additive");
            //lineRenderer.material.color = color;
            lineRenderer.material.SetColor("_TintColor", color);
            lineRenderer.SetPosition(0, sPoint);
            lineRenderer.SetPosition(1, ePoint);
            lineRenderer.SetWidth(0.15f, 0.2f);
            lineRenderer.enabled = true;

            gameObject.AddComponent<DestroyIfEditMode>();
            
        }

        private void Update()
        {
            if (!isCollision)
            {
                if (Time.timeScale == 0f) return;

                _time = Time.smoothDeltaTime / Time.timeScale;
                Vector3 gravityVelocity = (!StatMaster.GodTools.GravityDisabled) ? (GravityAcceleration * _time) : Vector3.zero;
                Vector3 dragVelocity = (-(direction * Drag) / Mass) * _time;
                Velocity = Velocity + gravityVelocity + dragVelocity;
                ePoint = sPoint + Velocity * _time;
                direction = -(sPoint - ePoint).normalized;
                lineRenderer.SetPosition(0, sPoint);          

                if (Physics.Raycast(sPoint, direction, out hitInfo, (sPoint - ePoint).magnitude))
                {
                    if (hitInfo.rigidbody != null)
                    {
                        var v = (Velocity * Mass) / (hitInfo.rigidbody.mass);
                        var f = v / _time;
                        hitInfo.rigidbody.AddForceAtPosition(f, hitInfo.point);
                    }

                    lineRenderer.SetPosition(1, hitInfo.point);
                    isCollision = true;
                }
                else
                {
                    lineRenderer.SetPosition(1, ePoint);
                    sPoint = ePoint;
                }         
            }
            else
            {
                lineRenderer.enabled = false;
                Destroy(gameObject);
            }




        }
    }

}
